import sys

from Tkinter import *
from math    import *
from random  import *

class Staff:
    gap   = 5
    count = 5

    def __init__ ( self, canvas, posx, posy, width ):
        self.x, self.y, self.l = posx, posy, width
        self.canvas = canvas
        line = lambda x, y, l: [x, y, x+l, y]
        self.lines = [line ( posx, posy+Staff.gap*i, width ) for i in range ( Staff.count )]
        self.view  = [canvas.create_line ( l ) for l in self.lines]

    def create_extra_top ( self, count ):
        line = lambda x, y, l: [x+l/4, y, x+l*3/4, y]
        lines = [line ( self.x, self.y-Staff.gap*(i+1), self.l ) for i in range ( count )]
        return [self.canvas.create_line ( l ) for l in lines]

    def create_extra_bottom ( self, count ):
        line = lambda x, y, l: [x+l/4, y, x+l*3/4, y]
        lines = [line ( self.x, self.y+Staff.gap*(i+Staff.count), self.l ) for i in range ( count )]
        return [self.canvas.create_line ( l ) for l in lines]

class Note:
    all    = 'agfedcbagfedcbagfedcbagfe'
    radius = Staff.gap/2
    
    top_idx    = 8
    bottom_idx = len ( all ) - 6
    
    def __init__ ( self, staff, idx, fill ):
        self.value = Note.all[idx]
        self.staff = staff
        self.idx   = idx
        self.x = staff.x + staff.l/2
        self.y = staff.y + ( idx - 1 - Note.top_idx ) * Staff.gap / 2
        points = []
        self.view = []
        if idx <= Note.top_idx:
            self.view += staff.create_extra_top ( ( Note.top_idx - idx + 1 ) / 2 )
        elif idx >= Note.bottom_idx:
            self.view += staff.create_extra_bottom ( 1 + ( idx - Note.bottom_idx ) / 2 )
        for i in range ( 360 ):
            points.append ( self.x + Note.radius * cos ( radians ( i ) ) )
            points.append ( self.y + Note.radius * sin ( radians ( i ) ) )
        self.view += [ staff.canvas.create_line ( points, fill=fill ) ]

    def done ( self ):
        self.staff.canvas.delete ( *self.view )

class App ( Tk ):
    def __init__ ( self ):
        Tk.__init__ ( self )
        self.title ( '?' )
        self.bind ( '<Any-Key>', self.do_key )
        self.geometry ('80x80+500+300')
        self.canvas = Canvas ()
        self.canvas.pack ()

        self.staff = Staff ( self.canvas, posx=20, posy=30, width=20 )
        self.note  = None

        self.roll ()
        self.mainloop ()

    def roll ( self, fill='blue' ):
        if self.note:
            idx = self.note.idx
            self.note.done ()
        else:
            idx = -1
        while True:
            r = randint ( 0, len ( Note.all ) - 1 )
            if r != idx:
                break
        self.note = Note ( self.staff, r, fill )

    def do_key ( self, e ):
        if e.keysym == 'Escape':
            sys.exit ()
        self.roll ( 'blue' if self.note and e.keysym == self.note.value else 'red' )

App ()
